#region Using directives

using System;

#endregion

namespace Hanoi.Utils
{
    /// <summary>
    /// Summary description for LevelEvaluation.
    /// </summary>
    public class LevelEvaluation
    {
        #region Hashtables...
        private int[] _sizeLevel = new int[] { 0, 0, 0, 1, 1, 2, 2, 3 };
        private int[][] _movesLevelValue = new int[][]
            {
                new int[] {0,0,0,0},
                new int[] {1,0,0,0},
                new int[] {1,1,0,0},
                new int[] {1,1,1,0},
                new int[] {0,0,0,-1}
            };
        private int[][] _secondsMoveLevelValue = new int[][]
            {
                new int[] {1,0,0,0},
                new int[] {1,1,-1,-1},
                new int[] {1,1,0,-1},
                new int[] {1,1,0,-1},
                new int[] {0,0,0,-1},
            };
        #endregion


        #region Members, properties and c'tor
        private IGame _game;

        public IGame Game
        {
            get { return _game; }
            set { _game = value; }
        }

        public LevelEvaluation(IGame game)
        {
            _game = game;
        }

        public int Level
        {
            get
            {
                return Calc();
            }
        }

        private int Calc()
        {
            int t = 0;
            int level = _game.Size - 1;

            t = _sizeLevel[level];
            t = AddMovesPayload(t, (double)_game.Moves / ((Profiles.ProfileBase)_game).CalculateMoves(_game.Size));
            if (_game.TimeControled)
                t = AddSecondsPayload(t, Convert.ToInt32(_game.TimeAmount.TotalSeconds / _game.Moves));
            t = ReCalc(t);

            return t;
        }

        private int ReCalc(int x)
        {
            if (x < 0)
                return 0;
            else if (x > 4)
                return 4;
            else
                return x;
        }


        private int AddMovesPayload(int level, double x)
        {
            int columnIndex = MovesColumnIndex(x);
            return level + _movesLevelValue[level][columnIndex];
        }

        private int MovesColumnIndex(double x)
        {
            int columnIndex;
            if (x <= 1)
                columnIndex = 0;
            else if (x > 1 && x <= 1.25)
                columnIndex = 1;
            else if (x > 1.25 && x <= 1.5)
                columnIndex = 2;
            else
                columnIndex = 3;
            return columnIndex;
        }

        private int AddSecondsPayload(int level, int seconds)
        {
            int columnIndex = SecondsColumnIndex(seconds);
            return level + _secondsMoveLevelValue[level][columnIndex];
        }

        private int SecondsColumnIndex(int s)
        {
            int columnIndex;
            if (s <= 1)
                columnIndex = 0;
            else if (s > 1 && s <= 2)
                columnIndex = 1;
            else if (s > 2 && s <= 5)
                columnIndex = 2;
            else
                columnIndex = 3;
            return columnIndex;
        }

        #endregion
    }
}
